#include "LeGraphicsItemLayer.h"

#include "LeGraphicsItem.h"
#include "LeGraphicsPalette.h"
#include "LeGraphicsScene.h"

LeGraphicsItemLayer::LeGraphicsItemLayer(const QString &name)
    : QGraphicsObject()
    , m_fullName(name)
{
    setFlag(ItemHasNoContents);
    m_featureItemMap.insert(GftPad, new LeGraphicsCompositeItem(GftPad, this));
    m_featureItemMap.insert(GftPin, new LeGraphicsCompositeItem(GftPin, this));
    m_featureItemMap.insert(GftFiducial, new LeGraphicsCompositeItem(GftFiducial, this));
    m_featureItemMap.insert(GftHole, new LeGraphicsCompositeItem(GftHole, this));
    m_featureItemMap.insert(GftSlot, new LeGraphicsCompositeItem(GftSlot, this));
    m_featureItemMap.insert(GftFill, new LeGraphicsCompositeItem(GftFill, this));
    m_featureItemMap.insert(GftTrace, new LeGraphicsCompositeItem(GftTrace, this));
    m_featureItemMap.insert(GftText, new LeGraphicsCompositeItem(GftText, this));
    m_featureItemMap.insert(GftNone, new LeGraphicsCompositeItem(GftNone, this));
}

LeGraphicsItemLayer::~LeGraphicsItemLayer()
{

}

void LeGraphicsItemLayer::setNames(const QString &fullName, const QString &shortName, const QString &tinyName)
{
    setFullName(fullName);
    setShortName(shortName);
    setTinyName(tinyName);
}

QString LeGraphicsItemLayer::fullName() const
{
    return m_fullName;
}

QString LeGraphicsItemLayer::shortName() const
{
    return m_shortName;
}

QString LeGraphicsItemLayer::tinyName() const
{
    return m_tinyName;
}

void LeGraphicsItemLayer::addToLayer(LeGraphicsItem *item)
{
    addToLayer(QList<LeGraphicsItem*>() << item);
}

void LeGraphicsItemLayer::addToLayer(const QList<LeGraphicsItem *> &items)
{
    for (auto item: items)
    {
        Q_ASSERT(m_featureItemMap.contains(item->featureType()));
        Q_ASSERT(!m_featureItemMap.value(item->featureType())->childItems().contains(item));
        item->setParentItem(m_featureItemMap.value(item->featureType()));
    }
}

// TBD: remove from scene as weel.
// If the caller forget to delete the item or remove it from scene,
// this will crash in paintEvent since the item doesn't have a parent
// layer which is needed to get the palette
LeGraphicsItem *LeGraphicsItemLayer::removeFromLayer(LeGraphicsItem *item)
{
    Q_ASSERT(m_featureItemMap.contains(item->featureType()));
    Q_ASSERT(m_featureItemMap.value(item->featureType())->childItems().contains(item));
    item->setParentItem(nullptr);
    if (scene() != nullptr)
        scene()->removeItem(item);
    return item;
}

QList<LeGraphicsItem *> LeGraphicsItemLayer::items() const
{
    QList<LeGraphicsItem *> result;
    for (auto roleItem: m_featureItemMap.values())
        for (auto child: roleItem->childItems())
            result.append(static_cast<LeGraphicsItem*>(child));
    return result;
}

void LeGraphicsItemLayer::setFeatureOption(const LeGraphicsFeatureOption &option)
{
    if (m_featureOption == option)
        return;

    m_featureOption = option;
    m_featureItemMap.value(GftFiducial)->setVisible(option.isFeatureVisible(GftFiducial));
    m_featureItemMap.value(GftFill)->setVisible(option.isFeatureVisible(GftFill));
    m_featureItemMap.value(GftHole)->setVisible(option.isFeatureVisible(GftHole));
    m_featureItemMap.value(GftPad)->setVisible(option.isFeatureVisible(GftPad));
    m_featureItemMap.value(GftPin)->setVisible(option.isFeatureVisible(GftPin));
    m_featureItemMap.value(GftSlot)->setVisible(option.isFeatureVisible(GftSlot));
    m_featureItemMap.value(GftText)->setVisible(option.isFeatureVisible(GftText));
    m_featureItemMap.value(GftTrace)->setVisible(option.isFeatureVisible(GftTrace));
    if (scene() != nullptr)
        scene()->update();
}

LeGraphicsFeatureOption LeGraphicsItemLayer::featureOption() const
{
    return m_featureOption;
}

LeGraphicsPalette LeGraphicsItemLayer::graphicsPalette(LeGraphicsFeature feature) const
{
    LeGraphicsPalette result = graphicsScene()->graphicsPalette();
    result.setBrush(LeGraphicsPalette::Feature, m_featureOption.featureBrush(feature));
    return result;
}

LeGraphicsScene *LeGraphicsItemLayer::graphicsScene() const
{
    return qobject_cast<LeGraphicsScene*>(scene());
}

void LeGraphicsItemLayer::setFullName(QString fullName)
{
    if (m_fullName == fullName)
        return;

    m_fullName = fullName;
    emit fullNameChanged(fullName);
}

void LeGraphicsItemLayer::setShortName(QString shortName)
{
    if (m_shortName == shortName)
        return;

    m_shortName = shortName;
    emit shortNameChanged(shortName);
}

void LeGraphicsItemLayer::setTinyName(QString tinyName)
{
    if (m_tinyName == tinyName)
        return;

    m_tinyName = tinyName;
    emit tinyNameChanged(tinyName);
}

void LeGraphicsItemLayer::setFeaturesVisible(LeGraphicsFeature type, bool visible)
{
    Q_ASSERT(m_featureItemMap.contains(type));
    m_featureItemMap.value(type)->setVisible(visible);
}

void LeGraphicsItemLayer::clear()
{
    for (auto roleItem: m_featureItemMap.values())
    {
        for (auto item: roleItem->childItems())
        {
            item->setParentItem(nullptr);
            delete item;
        }
    }
}

QRectF LeGraphicsItemLayer::boundingRect() const
{
    return QRect();
}

void LeGraphicsItemLayer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(painter)
    Q_UNUSED(option)
    Q_UNUSED(widget)
}
